import Table from "../../packages/table";
import TableColumn from "../../packages/table/src/table-column";

const createTableColumns = ({ prop, label, fixed, width }) => ({
  render() {
    return (
      <TableColumn prop={prop} label={label} fixed={fixed} width={width} />
    );
  },
});

function generateRandomString(length) {
  let result = "";
  const characters =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  const charactersLength = characters.length;
  for (let i = 0; i < length; i++) {
    result += characters.charAt(Math.floor(Math.random() * charactersLength));
  }
  return result;
}

function mockTableData(columns, rows) {
  const tableData = [];

  for (let i = 0; i < rows; i++) {
    const rowData = {};

    for (const column of columns) {
      if (column.type === "string") {
        rowData[column.field] = generateRandomString(8);
      } else if (column.type === "number") {
        rowData[column.field] = Math.floor(Math.random() * 20);
      } else {
        rowData[column.field] = "";
      }
    }

    tableData.push(rowData);
  }

  return tableData;
}

describe("Table", () => {
  it("合计行插槽渲染正常", () => {
    const tableData = [
      {
        id: "12987122",
        name: "王小虎",
        amount1: "234",
        amount2: "3.2",
        amount3: 10,
      },
      {
        id: "12987123",
        name: "王小虎",
        amount1: "165",
        amount2: "4.43",
        amount3: 12,
      },
      {
        id: "12987124",
        name: "王小虎",
        amount1: "324",
        amount2: "1.9",
        amount3: 9,
      },
      {
        id: "12987125",
        name: "王小虎",
        amount1: "621",
        amount2: "2.2",
        amount3: 17,
      },
      {
        id: "12987126",
        name: "王小虎",
        amount1: "539",
        amount2: "4.1",
        amount3: 15,
      },
    ];

    const amountLabel = "数量";

    cy.mount(Table, {
      propsData: {
        data: tableData,
        showSummary: true,
      },
      slots: {
        default: [
          createTableColumns({ prop: "id", label: "ID" }),
          createTableColumns({ prop: "name", label: "姓名" }),
          createTableColumns({ prop: "amount1", label: amountLabel }),
        ],
      },
      scopedSlots: {
        summary: `<div class="summary-item">{{props.column.label}}:{{props.sum}}元</div>`,
      },
    });

    cy.get(".summary-item")
      .contains(`${amountLabel}:1883元`)
      .should("be.visible");
  });

  it("Position:sticky渲染 合计行", () => {
    const tableData = [
      {
        id: "12987122",
        name: "王小虎",
        amount1: "234",
        amount2: "3.2",
        amount3: 10,
      },
      {
        id: "12987123",
        name: "王小虎",
        amount1: "165",
        amount2: "4.43",
        amount3: 12,
      },
      {
        id: "12987124",
        name: "王小虎",
        amount1: "324",
        amount2: "1.9",
        amount3: 9,
      },
      {
        id: "12987125",
        name: "王小虎",
        amount1: "621",
        amount2: "2.2",
        amount3: 17,
      },
      {
        id: "12987126",
        name: "王小虎",
        amount1: "539",
        amount2: "4.1",
        amount3: 15,
      },
    ];

    const amountLabel = "数量";

    cy.mount(Table, {
      propsData: {
        data: tableData,
        showSummary: true,
        stickyFixed: true,
      },
      slots: {
        default: [
          createTableColumns({ prop: "id", label: "ID" }),
          createTableColumns({ prop: "name", label: "姓名" }),
          createTableColumns({
            prop: "amount1",
            label: amountLabel,
            fixed: "right",
          }),
        ],
      },
      scopedSlots: {
        summary: `<div class="summary-item">{{props.column.label}}:{{props.sum}}元</div>`,
      },
    });

    cy.get(".summary-item")
      .contains(`${amountLabel}:1883元`)
      .should("be.visible");
  });

  it("Position:sticky渲染 固定列正常", () => {
    const tableData = [
      {
        id: "12987122",
        name: "王小虎",
        amount1: "234",
        amount2: "3.2",
        amount3: 10,
      },
      {
        id: "12987123",
        name: "王小虎",
        amount1: "165",
        amount2: "4.43",
        amount3: 12,
      },
      {
        id: "12987124",
        name: "王小虎",
        amount1: "324",
        amount2: "1.9",
        amount3: 9,
      },
      {
        id: "12987125",
        name: "王小虎",
        amount1: "621",
        amount2: "2.2",
        amount3: 17,
      },
      {
        id: "12987126",
        name: "王小虎",
        amount1: "539",
        amount2: "4.1",
        amount3: 15,
      },
    ];

    cy.mount(Table, {
      propsData: {
        stickyFixed: true,
        data: tableData,
      },
      slots: {
        default: [
          createTableColumns({ prop: "id", label: "ID", fixed: "left" }),
          createTableColumns({ prop: "name", label: "姓名" }),
          createTableColumns({ prop: "amount1", label: "数量1" }),
          createTableColumns({
            prop: "amount2",
            label: "数量2",
            fixed: "right",
          }),
        ],
      },
    });
    cy.get(".z-table__body-wrapper").should("have.length", 1);
    cy.get(".z-table__header th.is-fixed-cell").should("have.length", 2);
    cy.get(".z-table__header th")
      .first()
      .then(($first) => {
        const className = $first.attr("class");
        const offsetStyle = $first.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("left: 0px;");
      });

    cy.get(".z-table__header th")
      .contains("数量2")
      .parent()
      .then(($th) => {
        const className = $th.attr("class");
        const offsetStyle = $th.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 0px;");
      });
  });

  it("Position:sticky渲染 多个固定列正常", () => {
    const tableData = mockTableData(
      [
        {
          type: "number",
          field: "id",
        },
        {
          type: "string",
          field: "name",
        },
        {
          type: "number",
          field: "amount1",
        },
        {
          type: "number",
          field: "amount2",
        },
      ],
      20
    );

    cy.mount(Table, {
      propsData: {
        stickyFixed: true,
        data: tableData,
      },
      slots: {
        default: [
          createTableColumns({
            prop: "id",
            label: "ID",
            fixed: "left",
            width: 100,
          }),
          createTableColumns({ prop: "name", label: "姓名" }),
          createTableColumns({
            prop: "amount1",
            label: "数量1",
            fixed: "left",
            width: 120,
          }),
          createTableColumns({
            prop: "amount3",
            label: "数量3",
            fixed: "left",
          }),
          createTableColumns({
            prop: "amount2",
            label: "数量2",
            fixed: "right",
          }),
          createTableColumns({
            prop: "amount2",
            label: "数量2-2",
            fixed: "right",
            width: 120,
          }),
          createTableColumns({
            prop: "amount2",
            label: "数量2-1",
            fixed: "right",
            width: 120,
          }),
        ],
      },
    });
    cy.get(".z-table__body-wrapper").should("have.length", 1);
    cy.get(".z-table__header th.is-fixed-cell").should("have.length", 6);
    cy.get(".z-table__header th")
      .eq(1)
      .then(($second) => {
        const className = $second.attr("class");
        const offsetStyle = $second.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("left: 100px;");
      });

    cy.get(".z-table__header th")
      .eq(2)
      .then(($third) => {
        const className = $third.attr("class");
        const offsetStyle = $third.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("left: 220px;");
      });

    cy.get(".z-table__body tr:nth(0) td")
      .eq(2)
      .then(($third) => {
        const className = $third.attr("class");
        const offsetStyle = $third.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("left: 220px;");
      });

    cy.get(".z-table__body tr:nth(0) td")
      .eq(-1)
      .then(($third) => {
        const className = $third.attr("class");
        const offsetStyle = $third.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 0px;");
      });

    cy.get(".z-table__header th")
      .contains("数量2")
      .parent()
      .then(($third) => {
        const className = $third.attr("class");
        const offsetStyle = $third.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 240px;");
      });

    cy.get(".z-table__body tr:nth(0) td")
      .eq(-3)
      .then(($third) => {
        const className = $third.attr("class");
        const offsetStyle = $third.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 240px;");
      });
  });

  it("Position:sticky渲染 固定列+滚动条", () => {
    const tableData = mockTableData(
      [
        {
          type: "number",
          field: "id",
        },
        {
          type: "string",
          field: "name",
        },
        {
          type: "number",
          field: "amount1",
        },
        {
          type: "number",
          field: "amount2",
        },
        {
          type: "number",
          field: "amount3",
        },
        {
          type: "number",
          field: "amount4",
        },
        {
          type: "number",
          field: "amount5",
        },
        {
          type: "number",
          field: "amount6",
        },
      ],
      20
    );

    cy.mount(Table, {
      propsData: {
        stickyFixed: true,
        data: tableData,
        height: "300px",
      },
      slots: {
        default: [
          createTableColumns({ prop: "id", label: "ID", fixed: "left" }),
          createTableColumns({ prop: "name", label: "姓名" }),
          createTableColumns({
            prop: "amount3",
            label: "数量3",
          }),
          createTableColumns({
            prop: "amount4",
            label: "数量4",
          }),
          createTableColumns({
            prop: "amount5",
            label: "数量5",
          }),
          createTableColumns({
            prop: "amount6",
            label: "数量6",
          }),
          createTableColumns({
            prop: "amount2",
            label: "数量1",
            fixed: "right",
          }),
          createTableColumns({
            prop: "amount2",
            label: "数量2",
            fixed: "right",
            width: 100,
          }),
        ],
      },
    });
    cy.get(".z-table__body-wrapper").should("have.length", 1);
    cy.get(".z-table__header th.is-fixed-cell").should("have.length", 3);
    cy.get(".z-table__header th")
      .contains("数量1")
      .parent()
      .then(($second) => {
        const className = $second.attr("class");
        const offsetStyle = $second.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 115px;");
      });

    cy.get(".z-table__body tr:nth(0) td")
      .eq(-1)
      .then(($second) => {
        const className = $second.attr("class");
        const offsetStyle = $second.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 0px;");
      });
  });

  it("Position:sticky渲染 合并行列", () => {
    const tableData = mockTableData(
      [
        {
          type: "number",
          field: "id",
        },
        {
          type: "string",
          field: "name",
        },
        {
          type: "number",
          field: "amount1",
        },
        {
          type: "number",
          field: "amount2",
        },
        {
          type: "number",
          field: "amount3",
        },
        {
          type: "number",
          field: "amount4",
        },
        {
          type: "number",
          field: "amount5",
        },
        {
          type: "number",
          field: "amount6",
        },
      ],
      20
    );

    function objectSpanMethod({ row, column, rowIndex, columnIndex }) {
      if (columnIndex === 0) {
        if (rowIndex % 2 === 0) {
          return {
            rowspan: 2,
            colspan: 1,
          };
        } else {
          return {
            rowspan: 0,
            colspan: 0,
          };
        }
      }
    }

    cy.mount(Table, {
      propsData: {
        stickyFixed: true,
        data: tableData,
        height: "300px",
        spanMethod: objectSpanMethod,
      },
      slots: {
        default: [
          createTableColumns({ prop: "id", label: "ID", fixed: "left" }),
          createTableColumns({ prop: "name", label: "姓名" }),
          createTableColumns({
            prop: "amount3",
            label: "数量3",
          }),
          createTableColumns({
            prop: "amount4",
            label: "数量4",
          }),
          createTableColumns({
            prop: "amount5",
            label: "数量5",
          }),
          createTableColumns({
            prop: "amount6",
            label: "数量6",
          }),
          createTableColumns({
            prop: "amount2",
            label: "数量1",
            fixed: "right",
          }),
          createTableColumns({
            prop: "amount2",
            label: "数量2",
            fixed: "right",
            width: 100,
          }),
        ],
      },
    });
    cy.get(".z-table__body-wrapper").should("have.length", 1);
    cy.get(".z-table__header th.is-fixed-cell").should("have.length", 3);
    cy.get(".z-table__body td")
      .first()
      .then(($first) => {
        const className = $first.attr("class");
        const offsetStyle = $first.attr("style");
        const rowspan = $first.attr("rowspan");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("left: 0px;");
        expect(rowspan).eq("2");
      });
  });

  it("Position:sticky渲染 树形", () => {
    const tableData = [
      {
        id: 1,
        date: "2016-05-02",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1518 弄",
      },
      {
        id: 2,
        date: "2016-05-04",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1517 弄",
      },
      {
        id: 3,
        date: "2016-05-01",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1519 弄",
        children: [
          {
            id: 31,
            date: "2016-05-01",
            name: "王小虎",
            address: "上海市普陀区金沙江路 1519 弄",
          },
          {
            id: 32,
            date: "2016-05-01",
            name: "王小虎",
            address: "上海市普陀区金沙江路 1519 弄",
          },
        ],
      },
      {
        id: 4,
        date: "2016-05-03",
        name: "王小虎",
        address: "上海市普陀区金沙江路 1516 弄",
      },
    ];

    cy.mount(Table, {
      propsData: {
        stickyFixed: true,
        data: tableData,
        height: "300px",
        rowKey: "id",
        border: true,
        defaultExpandAll: true,
      },
      slots: {
        default: [
          createTableColumns({ prop: "id", label: "ID", fixed: "left" }),
          createTableColumns({ prop: "date", label: "日期" }),
          createTableColumns({ prop: "name", label: "姓名" }),
          createTableColumns({ prop: "address", label: "地址" }),
        ],
      },
    });
    cy.get(".z-table__body-wrapper").should("have.length", 1);
    cy.get(".z-table__header th.is-fixed-cell").should("have.length", 1);
    cy.get(".z-table__body .z-table__row--level-1 td")
      .first()
      .then(($first) => {
        const className = $first.attr("class");
        const offsetStyle = $first.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("left: 0px;");
      });
  });

  it("Position:sticky渲染 多级表头", () => {
    const tableData = mockTableData(
      [
        {
          type: "number",
          field: "id",
        },
        {
          type: "string",
          field: "name",
        },
        {
          type: "number",
          field: "amount1",
        },
        {
          type: "number",
          field: "amount2",
        },
        {
          type: "number",
          field: "amount3",
        },
        {
          type: "number",
          field: "amount4",
        },
        {
          type: "number",
          field: "amount5",
        },
        {
          type: "number",
          field: "amount6",
        },
      ],
      20
    );

    const Demo = {
      template: `
        <z-table sticky-fixed :data="tableData" :height="300" style="width: 600px">
            <z-table-column
      prop="id"
      label="ID"
      fixed
      width="150">
    </z-table-column>
    <z-table-column label="配送信息">
      <z-table-column
        prop="name"
        label="姓名"
        width="120">
      </z-table-column>
        <z-table-column
          prop="amount1"
          label="数量1"
          width="120">
        </z-table-column>
        </z-table-column>
        <z-table-column
          prop="amount2"
          label="数量2"
          width="120">
        </z-table-column>
        <z-table-column
          prop="amount3"
          label="数量3"
          fixed="right"
          width="120">
        </z-table-column>
        <z-table-column
          prop="amount4"
          label="数量4"
          fixed="right"
          width="120">
        </z-table-column>
        </z-table>
      `,
      data() {
        return {
          tableData,
        };
      },
    };

    cy.mount(Demo, {
      stubs: {
        "z-table": Table,
        "z-table-column": TableColumn,
      },
    });
    cy.get(".z-table__body-wrapper").should("have.length", 1);
    cy.get(".z-table__header th.is-fixed-cell").should("have.length", 3);
    cy.get(".z-table__header th")
      .first()
      .then(($second) => {
        const className = $second.attr("class");
        const offsetStyle = $second.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("left: 0px;");
      });

    cy.get(".z-table__header th")
      .contains("数量3")
      .parent()
      .then(($th) => {
        const className = $th.attr("class");
        const offsetStyle = $th.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 135px;");
      });

    cy.get(".z-table__header th")
      .contains("数量4")
      .parent()
      .then(($th) => {
        const className = $th.attr("class");
        const offsetStyle = $th.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 15px;");
      });
  });

  it("Position:sticky渲染 右侧固定列为多级表头", () => {
    const tableData = mockTableData(
      [
        {
          type: "number",
          field: "id",
        },
        {
          type: "string",
          field: "name",
        },
        {
          type: "number",
          field: "amount1",
        },
        {
          type: "number",
          field: "amount2",
        },
        {
          type: "number",
          field: "amount3",
        },
        {
          type: "number",
          field: "amount4",
        },
        {
          type: "number",
          field: "amount5",
        },
        {
          type: "number",
          field: "amount6",
        },
      ],
      20
    );

    const Demo = {
      template: `
      <z-table sticky-fixed :data="tableData" :height="300" style="width: 600px">
         <z-table-column
            prop="id"
            label="ID"
            fixed
            width="150">
         </z-table-column>
         <z-table-column label="配送信息">
            <z-table-column
               prop="name"
               label="姓名"
               width="120">
            </z-table-column>
            <z-table-column
               prop="amount1"
               label="数量1"
               width="120">
            </z-table-column>
         </z-table-column>
         <z-table-column
            prop="amount2"
            label="数量2"
            width="120">
         </z-table-column>
         <z-table-column
            prop="amount2"
            label="数量2"
            width="120">
         </z-table-column>
         <z-table-column
            prop="amount3"
            label="数量3"
            fixed="right"
            width="120">
            <z-table-column
               prop="amount2"
               label="数量2-fixed"
               width="120">
            </z-table-column>
            <z-table-column
               prop="amount4"
               label="数量4-fixed"
               width="80">
            </z-table-column>
         </z-table-column>
      </z-table>
      `,
      data() {
        return {
          tableData,
        };
      },
    };

    cy.mount(Demo, {
      stubs: {
        "z-table": Table,
        "z-table-column": TableColumn,
      },
    });
    cy.get(".z-table__body-wrapper").should("have.length", 1);
    cy.get(".z-table__header th.is-fixed-cell").should("have.length", 4);
    cy.get(".z-table__header th")
      .first()
      .then(($second) => {
        const className = $second.attr("class");
        const offsetStyle = $second.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("left: 0px;");
      });

    cy.get(".z-table__header th")
      .contains("数量3")
      .parent()
      .then(($th) => {
        const className = $th.attr("class");
        const offsetStyle = $th.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 15px;");
      });

    cy.get(".z-table__header th")
      .contains("数量4-fixed")
      .parent()
      .then(($th) => {
        const className = $th.attr("class");
        const offsetStyle = $th.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 15px;");
      });

    cy.get(".z-table__body tr:nth(0) td")
      .eq(-1)
      .then(($second) => {
        const className = $second.attr("class");
        const offsetStyle = $second.attr("style");
        expect(className).contain("is-fixed-cell");
        expect(offsetStyle).eq("right: 0px;");
      });
  });
});
